library dxwidget_loading;

import 'package:erp_widget/src/utils/screen/index.dart';
import 'package:flutter/material.dart';

import 'decorate/decorate.dart';
import 'indicators/audio_equalizer.dart';
import 'indicators/ball_beat.dart';
import 'indicators/ball_clip_rotate.dart';
import 'indicators/ball_clip_rotate_multiple.dart';
import 'indicators/ball_clip_rotate_pulse.dart';
import 'indicators/ball_grid_beat.dart';
import 'indicators/ball_grid_pulse.dart';
import 'indicators/ball_pulse.dart';
import 'indicators/ball_pulse_rise.dart';
import 'indicators/ball_pulse_sync.dart';
import 'indicators/ball_rotate.dart';
import 'indicators/ball_rotate_chase.dart';
import 'indicators/ball_scale.dart';
import 'indicators/ball_scale_multiple.dart';
import 'indicators/ball_scale_ripple.dart';
import 'indicators/ball_scale_ripple_multiple.dart';
import 'indicators/ball_spin_fade_loader.dart';
import 'indicators/ball_triangle_path.dart';
import 'indicators/ball_triangle_path_colored.dart';
import 'indicators/ball_zig_zag.dart';
import 'indicators/ball_zig_zag_deflect.dart';
import 'indicators/circle_stroke_spin.dart';
import 'indicators/cube_transition.dart';
import 'indicators/line_fat_spin_fade_loader.dart';
import 'indicators/line_scale.dart';
import 'indicators/line_scale_party.dart';
import 'indicators/line_scale_pulse_out.dart';
import 'indicators/line_scale_pulse_out_rapid.dart';
import 'indicators/line_thin_spin_fade_loader.dart';
import 'indicators/orbit.dart';
import 'indicators/pacman.dart';
import 'indicators/semi_circle_spin.dart';
import 'indicators/square_spin.dart';
import 'indicators/triangle_skew_spin.dart';

///34 different types animation enums.
enum DxLoadingType {
  ballPulse,
  ballGridPulse,
  ballClipRotate,
  squareSpin,
  ballClipRotatePulse,
  ballClipRotateMultiple,
  ballPulseRise,
  ballRotate,
  cubeTransition,
  ballZigZag,
  ballZigZagDeflect,
  ballTrianglePath,
  ballTrianglePathColored,
  ballTrianglePathColoredFilled,
  ballScale,
  lineScale,
  lineScaleParty,
  ballScaleMultiple,
  ballPulseSync,
  ballBeat,
  lineScalePulseOut,
  lineScalePulseOutRapid,
  ballScaleRipple,
  ballScaleRippleMultiple,
  ballSpinFadeLoader,
  lineFatSpinFadeLoader,
  lineThinSpinFadeLoader,
  triangleSkewSpin,
  pacman,
  ballGridBeat,
  semiCircleSpin,
  ballRotateChase,
  orbit,
  audioEqualizer,
  circleStrokeSpin,
}

/// Entrance of the loading.
class DxLoading extends StatelessWidget {
  /// Indicate which type.
  final DxLoadingType type;

  final double width;
  final double height;

  /// The color you draw on the shape.
  final List<Color>? colors;
  final Color? backgroundColor;

  /// The stroke width of line.
  final double? strokeWidth;

  /// Applicable to which has cut edge of the shape
  final Color? pathBackgroundColor;

  /// Animation status, true will pause the animation, default is false
  final bool pause;

  /// 是否垂直排列图标和文字内容
  final bool vertical;

  /// 加载文案
  final String? title;

  /// 文案样式
  final TextStyle? titleStyle;

  /// 文字与图标之间的距离
  final double space;

  const DxLoading({
    Key? key,
    this.width = 48,
    this.height = 48,
    required this.type,
    this.colors,
    this.backgroundColor,
    this.strokeWidth,
    this.pathBackgroundColor,
    this.vertical = true,
    this.title,
    this.titleStyle,
    this.space = 10,
    this.pause = false,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    if (type == DxLoadingType.circleStrokeSpin && pause) {
      debugPrint(
          "LoadingIndicator: it will not take any effect when set pause:true on ${DxLoadingType.circleStrokeSpin}");
    }
    List<Color> safeColors = colors == null || colors!.isEmpty ? [Theme.of(context).primaryColor] : colors!;

    Widget current = Container(
      width: width,
      height: height,
      color: backgroundColor,
      child: _buildIndicator(),
    );

    current = vertical
        ? Wrap(
            direction: Axis.vertical,
            crossAxisAlignment: WrapCrossAlignment.center,
            children: <Widget>[current, buildText()],
          )
        : Wrap(
            direction: Axis.horizontal,
            crossAxisAlignment: WrapCrossAlignment.center,
            children: <Widget>[current, buildText()],
          );

    return $LoadingDecorateContext(
      decorateData: $LoadingDecorateData(
        style: type,
        colors: safeColors,
        strokeWidth: strokeWidth,
        pathBackgroundColor: pathBackgroundColor,
        pause: pause,
      ),
      child: current,
    );
  }

  /// return the animation DxLoadingType.
  Widget _buildIndicator() {
    switch (type) {
      case DxLoadingType.ballPulse:
        return const $LoadingBallPulse();
      case DxLoadingType.ballGridPulse:
        return const $LoadingBallGridPulse();
      case DxLoadingType.ballClipRotate:
        return const $LoadingBallClipRotate();
      case DxLoadingType.squareSpin:
        return const $LoadingSquareSpin();
      case DxLoadingType.ballClipRotatePulse:
        return const $LoadingBallClipRotatePulse();
      case DxLoadingType.ballClipRotateMultiple:
        return const $LoadingBallClipRotateMultiple();
      case DxLoadingType.ballPulseRise:
        return const $LoadingBallPulseRise();
      case DxLoadingType.ballRotate:
        return const $LoadingBallRotate();
      case DxLoadingType.cubeTransition:
        return const $LoadingCubeTransition();
      case DxLoadingType.ballZigZag:
        return const $LoadingBallZigZag();
      case DxLoadingType.ballZigZagDeflect:
        return const $LoadingBallZigZagDeflect();
      case DxLoadingType.ballTrianglePath:
        return const $LoadingBallTrianglePath();
      case DxLoadingType.ballTrianglePathColored:
        return const $LoadingBallTrianglePathColored();
      case DxLoadingType.ballTrianglePathColoredFilled:
        return const $LoadingBallTrianglePathColored(isFilled: true);
      case DxLoadingType.ballScale:
        return const $LoadingBallScale();
      case DxLoadingType.lineScale:
        return const $LoadingLineScale();
      case DxLoadingType.lineScaleParty:
        return const $LoadingLineScaleParty();
      case DxLoadingType.ballScaleMultiple:
        return const $LoadingBallScaleMultiple();
      case DxLoadingType.ballPulseSync:
        return const $LoadingBallPulseSync();
      case DxLoadingType.ballBeat:
        return const $LoadingBallBeat();
      case DxLoadingType.lineScalePulseOut:
        return const $LoadingLineScalePulseOut();
      case DxLoadingType.lineScalePulseOutRapid:
        return const $LoadingLineScalePulseOutRapid();
      case DxLoadingType.ballScaleRipple:
        return const $LoadingBallScaleRipple();
      case DxLoadingType.ballScaleRippleMultiple:
        return const $LoadingBallScaleRippleMultiple();
      case DxLoadingType.ballSpinFadeLoader:
        return const $LoadingBallSpinFadeLoader();
      case DxLoadingType.lineFatSpinFadeLoader:
        return const $LoadingLineFatSpinFadeLoader();
      case DxLoadingType.lineThinSpinFadeLoader:
        return const $LoadingLineThinSpinFadeLoader();
      case DxLoadingType.triangleSkewSpin:
        return const $LoadingTriangleSkewSpin();
      case DxLoadingType.pacman:
        return const $LoadingPacman();
      case DxLoadingType.ballGridBeat:
        return const $LoadingBallGridBeat();
      case DxLoadingType.semiCircleSpin:
        return const $LoadingSemiCircleSpin();
      case DxLoadingType.ballRotateChase:
        return const $LoadingBallRotateChase();
      case DxLoadingType.orbit:
        return const $LoadingOrbit();
      case DxLoadingType.audioEqualizer:
        return const $LoadingAudioEqualizer();
      case DxLoadingType.circleStrokeSpin:
        return const $LoadingCircleStrokeSpin();
      default:
        throw Exception("no related DxLoadingType type:$DxLoadingType found");
    }
  }

  Widget buildText() {
    if (title != null) {
      return Padding(
        padding: EdgeInsets.only(left: vertical ? 0.0 : space, top: vertical ? space : 0.0),
        child: Text(
          title!,
          style: titleStyle ?? TextStyle(color: Colors.white, fontSize: 14.sp),
        ),
      );
    }

    return const SizedBox.shrink();
  }
}
